package com.android.flowoflife;

import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;

import com.android.flowoflife.hardware.ICameraAccess;
import com.android.flowoflife.hardware.SocketCameraAccess;
import com.android.flowoflife.hardware.StorageAccess;

public class FlowOfLife extends Activity implements OnClickListener {
	private StorageAccess storageAccess;
	private int captureFrameCount;
	private CountDownTimer captureTimer;
	private int replayFrameCount;
	private CountDownTimer replayTimer;
	private ICameraAccess cameraAccess;
	
	private TextView frameView;
	private ToggleButton captureButton;
	private Button replayButton;
	private ImageView imageView;
	
	
	class CameraAccessShutterCallback implements ShutterCallback {
		@Override
		public void onShutter() {
		}		
	}
	
	class CameraAccessRawPictureCallback implements PictureCallback {
		@Override
		public void onPictureTaken(byte[] data, Camera camera) {			
		}		
	}
	
	class CameraAccessJPEGPictureCallback implements PictureCallback {
		@Override
		public void onPictureTaken(byte[] data, Camera camera) {
			imageView.setImageBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
			
			try {
        		storageAccess.writeIntoExternalMemory(captureFrameCount, data);
        	} catch (IOException emioe) {
        		Log.e(IFlowOfLifeConstants.LOG_TAG, "External memory error", emioe);
        		
        		try {
	        		storageAccess.writeIntoInternalMemory(captureFrameCount, data);
	        	} catch (IOException imioe) {
	        		Log.e(IFlowOfLifeConstants.LOG_TAG, "Internal memory error", imioe);
	        	}
        	}
        	
        	cameraAccess.release();
		}		
	}
	

	private CameraAccessShutterCallback shutterCallback;
	private CameraAccessRawPictureCallback rawPictureCallback;
	private CameraAccessJPEGPictureCallback jpegPictureCallback;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);        
        
        frameView = (TextView) findViewById(R.id.frame);
        captureButton = (ToggleButton) findViewById(R.id.captureButton);
        captureButton.setOnClickListener(this);
        replayButton = (Button) findViewById(R.id.replayButton);
        replayButton.setOnClickListener(this);
        
        imageView = (ImageView) findViewById(R.id.imageview);
        //cameraAccess = new HTTPCameraAccess("http://192.168.1.60:8080", 240, 320);
//        cameraAccess = new CameraAccess(240, 320);
        cameraAccess = new SocketCameraAccess("192.168.1.5",9889,500, 500);
        storageAccess = new StorageAccess(this);
        
        shutterCallback = new CameraAccessShutterCallback();
		rawPictureCallback = new CameraAccessRawPictureCallback();
		jpegPictureCallback = new CameraAccessJPEGPictureCallback();
		
		captureFrameCount = 0;
        captureTimer = new CountDownTimer(30000, 1000) {
			@Override
			public void onFinish() {
				captureButton.setChecked(false);
			}
			@Override
			public void onTick(long millisUntilFinished) {
				captureFrameCount++;
				frameView.setText(getString(R.string.frame, new Object[]{Integer.valueOf(captureFrameCount)}));
				
				if (cameraAccess.lock()) {
					cameraAccess.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);
				}
			}        	
        };
        replayFrameCount = 0;
        replayTimer =  new CountDownTimer(1200, 40) {
			@Override
			public void onFinish() { }
			@Override
			public void onTick(long millisUntilFinished) {
				replayFrameCount++;
				frameView.setText(getString(R.string.frame, new Object[]{Integer.valueOf(replayFrameCount)}));
				
				InputStream inputStream = null;
				try {
					inputStream = storageAccess.readFromExternalMemory(replayFrameCount);
	        	} catch (IOException emioe) {
	        		Log.e(IFlowOfLifeConstants.LOG_TAG, "External memory error", emioe);
	        	}
	        	if (inputStream == null)
	        		return;
	        	try {
					inputStream = storageAccess.readFromInternalMemory(replayFrameCount);
	        	} catch (IOException emioe) {
	        		Log.e(IFlowOfLifeConstants.LOG_TAG, "Internal memory error", emioe);
	        	}
				
				imageView.setImageBitmap(BitmapFactory.decodeStream(inputStream));
				
				if (inputStream != null) {
					try {
						inputStream.close();
					} catch (IOException e) {
						Log.e(IFlowOfLifeConstants.LOG_TAG, "Internal memory error", e);
					}
				}
			}        	
        };
    }
    
    @Override
	protected void onDestroy() {
		captureTimer.cancel();
		super.onDestroy();
	}

	@Override
	public void onClick(View view) {
		if (view == captureButton) {
			if (captureButton.isChecked()) {
				captureFrameCount = 0;
				captureTimer.start();
			} else {
				captureTimer.cancel();
				captureFrameCount = 0;
			}
		} else if (view == replayButton) {
			replayFrameCount = 0;
			replayTimer.start();
		}
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.options_menu, menu);
	    return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.quit_menu:
			finish();
			return true;		
		}
		return false;
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		//TODO: use it if your want to save the data for the next application start
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		
		//TODO: save the data into the database
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		
		// TODO: read the data from the database and update GUI
	}
}